\chapter{Projekt unicore-beyond}

W tym rozdziale zaprezentowany zostanie projekt \texttt{unicore-beyond}. Jest prototypem
aplikacji, która ma wspomagać ludzi używających możliwości systemu gridowego Unicore w
codziennej pracy z programami na nim udostępnionymi. Dodatkowo jest pozytywnym przykładem
implementacji technik projektowania i pisania dużych aplikacji internetowych typu \emph{RIA} z
użyciem GWT, przedstawionych w poprzednim rozdziale.

\section{Opis}

Zadaniem aplikacji \texttt{unicore-beyond} jest umożliwienie stworzenia graficznego interfejsu dla
aplikacji udostępnionych w ramach systemu Unicore. Rolą użytkownika jest wyklikanie takiego
interfejsu za pomocą myszki, a nie pisanie go jako kodu XML lub Java.

Użytkownik ma dysponować zestawem przygotowanych wcześniej przez programistę pól, które może
dowolnie rozmieszczać i łączyć w grupy pól. Na koniec interfejs taki można zapisać w bazie danych i
stworzyć jego instację, wyglądającą tak samo jak podczas edycji. Można do niej wprowadzić dane,
które zostaną zwalidowane po stronie serwera.

Ostateczną funkcjonalnością, dodaną w przyszłości, będzie uruchomienie tak przygotowanej aplikacji na
systemie Unicore.

\section{Prezentacja}

W tym miejscu zostaną pokazane zrzuty ekranów aplikacji \texttt{unicore-beyond} podczas pracy z jej
instancją.

\subsection{Edytor \emph{Definicji Zadania}}

Edytor \emph{Definicji Zadania} miał od samego początku przypominać takie narzędzia jak QtDesigner
lub moduł Swing dla NetBeans. Jego celem jest edycja w sposób graficzny, znana pod pojęciem WYSIWIG
(ang. What You See Is What You Get), co znaczy w wolnym tłumaczeniu "to co widzisz, to dostaniesz".
Przedstawio to na Rysunku \ref{img:pic-ub-editor}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-editor}
\caption{Ekran edytora \emph{Definicji Zadania}.}
\label{img:pic-ub-editor}
\end{figure}

\subsubsection{Tworzenie \emph{Definicji Zadania}}

Pracę z edytorem rozpoczynamy utworzenia nowej \emph{Definicji Zadania}, po przez kliknięcie
przycisku "New Task". Powoduje to pojawienie się okna, które jest wizualną reprezentacją
\emph{Definicji Zadania}. Na samym początku należy wypełnić pola: nazwę aplikacji (pole "Name"), wersję
(pole "Version") oraz jej opis (pole "Description"), znajdujące się na karcie "Main". Ma to służyć
późniejszemu uruchamianiu aplikacji w systemie Unicore. Przedstawio to na Rysunku
\ref{img:pic-ub-new-task}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-new-task}
\caption{Tworzenie nowej \emph{Definicji Zadania}.}
\label{img:pic-ub-new-task}
\end{figure}

\subsubsection{Dodawanie \emph{Grup Wejść}}

Następnym krokiem powinno być dodanie odpowiedniej ilości \emph{Grup Wejść}, które będą porządkować
układane przez nas \emph{Definicje Wejść}. Są one reprezentowane jako zakładki w karcie "Inputs".
Dzięki temu układane przez nas pola będzie można podzielić na grupy w logiczny sposób.
Można to zrobić, przechodząc na kartę "Inputs" w podglądzie naszej nowej \emph{Definicji Zadania} i
kliknięciu na przycisku "Input Group" znajdującym się w panelu "Input / Output Toolbox", w lewej
dolnej części okna przeglądarki. Wynik tej operacji przedstawia Rysunek \ref{img:pic-ub-add-group}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-add-group}
\caption{Dodanie \emph{Grup Wejść}.}
\label{img:pic-ub-add-group}
\end{figure}

Dodane \emph{Grupy Wejść} otrzymują wygenerowane nazwy, które nie są intuicyjne. Należy je zmienić.
Służy do tego panel "Task Outline" w prawym górnym rogu okna przeglądarki. Jego zdaniem jest
pokazanie struktury całego tworzonego przez nas interfejsu oraz pomoc w jego modyfikacji. Widać, że dodane przez
nas wcześniej \emph{Grupy Wejść} pojawiły się w drzewie reprezentującym \emph{Definicję Zadania}. Po
kliknięciu na wybraną  \emph{Grupę Wejść} zostaje ona zaznaczona. Możliwe do wykonania na niej akcje
stają się aktywne (pasek narzędziowy u góry panelu). Można zmienić kolejność, usunąć lub zmienić
nazwę \emph{Grupy Wejść}. Zmianę nazwy pokazuje Rysunek \ref{img:pic-ub-change-group-name}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-change-group-name}
\caption{Zmiana nazw \emph{Grup Wejść}.}
\label{img:pic-ub-change-group-name}
\end{figure}

\subsubsection{Dodawanie \emph{Definicji Wejść}}

Teraz, gdy mamy odpowiednią dla nas ilość \emph{Grup Wejść}, możemy zacząć umieszczać w nich
\emph{Definicję Wejść}. Są one reprezentowane jako pola na zakładkach. Aby dodać nowe pole do
odpowiedniej zakładki, musi być ona aktywna (na wierzchu). Wygląd pola zależy od \emph{Typu
Wejścia}, który wybierzemy. Na Rysunku \ref{img:pic-ub-add-input} pokazany jest wynik dodania kilku
pól oraz zmiany ich nazw po przez panel "Task Outline". Akcje dostępne w tym panelu po zaznaczeniu
\emph{Definicji Wejścia} są analogiczne jak w przypadku \emph{Grupy Wejść}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-add-input}
\caption{Dodanie i zmiana nazw \emph{Definicji Wejść}.}
\label{img:pic-ub-add-input}
\end{figure}

\subsubsection{Dodawanie \emph{Grup Wyjść}}

Dodawanie \emph{Grup Wyjść} jest analogiczne do dodawania \emph{Grup Wejść}. Przedstawia to Rysunek
\ref{img:pic-ub-add-out-group}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-add-out-group}
\caption{Dodanie i zmiana nazw \emph{Grup Wyjść}.}
\label{img:pic-ub-add-out-group}
\end{figure}

\subsubsection{Dodawanie \emph{Definicji Wyjść}}

Dodawanie \emph{Definicji Wyjść} jest analogiczne do dodawania \emph{Definicji Wejść}. Przedstawia to Rysunek
\ref{img:pic-ub-add-output}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-add-output}
\caption{Dodanie i zmiana nazw \emph{Definicji Wyjść}.}
\label{img:pic-ub-add-output}
\end{figure}

\subsubsection{Modyfikacja \emph{Właściwości Definicji Wejść}}

Każdy z \emph{Typów Wejść} i \emph{Typów Wyjść} może posiadać \emph{Właściwości}, które można
zmodyfikować, aby odpowiednio dostosować pole do wprowadzonych danych. \emph{Właściwości} można
modyfikować po przez zaznaczenie w panelu "Task Outline" odpowiedniej \emph{Definicji}. Wówczas, w
panelu "Property Editor" w prawym dolnym rogu okna przeglądarki, pokazują się dostępne do edycji
\emph{Właściwości}. Po dwukrotnym kliknięciu na jakiejkolwiek z nich pojawia się okno edycji.
Prezentuje to Rysunek \ref{img:pic-ub-property}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-property}
\caption{Modyfikacja \emph{Właściwości}.}
\label{img:pic-ub-property}
\end{figure}

\subsubsection{Zapis \emph{Definicji Zadania}}

Po ostatecznym zakończeniu edycji \emph{Definicji Zadania}, klikamy na przycisk "Close" w dolnej
części okna podglądu. Aplikacja zapyta nas, czy chcemy zapisać zmiany. Oczywiście klikamy na
przycisku "Yes". Prezentuje to Rysunek \ref{img:pic-ub-save}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-save}
\caption{Zapis i kończenie edycji \emph{Definicji Zadania}.}
\label{img:pic-ub-save}
\end{figure}

Kończy to chwilo naszą przygodę z edytorem.

\subsection{Uruchamianie instancji \emph{Zadania}}

Spróbujemy teraz wprowadzić dane do naszego nowo utworzonego interfejsu aplikacji. W tym celu
przechodzimy na kartę "Task Runner", której przycisk znajduje się na samej górze po prawej stronie
okna przeglądrki.

\subsubsection{Tworzenie instacji \emph{Zadania}}

W tym miejscu pojawia się nam tylko panel menu uruchamiacza. Klikamy przycisk "Open". Pojawia się
nam okno, za pomocą którego możemy wybrać jedną z edytowanych wcześniej \emph{Definicji Zadań}.
Prezentuje to Rysunek \ref{img:pic-ub-open}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-open}
\caption{Wybór \emph{Definicji Zadania} do uruchomienia.}
\label{img:pic-ub-open}
\end{figure}

\subsubsection{Wprowadzanie danych do instancji \emph{Zadania}}

Po zaznaczeniu odpowiedniej \emph{Definicji Zadania} i kliknięciu przycisku "Open" pojawia się nam
okno instacji \emph{Zadania}. Możemy na nim wprowadzać dane do instacji \emph{Wejść}. Pokazuje to
Rysunek \ref{img:pic-ub-instance}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-instance}
\caption{Wprowadzanie danych do instancji \emph{Zadania}.}
\label{img:pic-ub-instance}
\end{figure}

\subsubsection{Walidacja wprowadzonych danych}

Ostatnią czynnością, na którą pozwala aplikacja \texttt{unicore-beyond} jest walidacja wprowadzonych
danych. Walidacja odbywa się po stronie serwera, po kliknięciu przycisku "Run". Jeśli wystąpią błędy
podczas jej wykonywania, zostaną wyświetlone odpowiednie komunikaty przy każdym z pól. Prezentuje to
Rysunek \ref{img:pic-ub-validation}.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{image/pic-ub-validation}
\caption{Wynik walidacji danych wprowadzonych do instancji \emph{Zadania}.}
\label{img:pic-ub-validation}
\end{figure}

\section{Struktura}

Podczas projektowania aplikacji \texttt{unicore-beyond} został wprowadzony jej podział na moduły. W
związku z użyciem Maven2 jako systemu budowania nie było problemu z zastosowaniem i utrzymywaniem
takiego rozróżnienia:

\begin{description}

\item[Moduł \texttt{unicore-beyond-api}] Znajdują się w nim klasy reprezentujące model danych,
interfejsy serwisów, obiekty transferowe oraz wyjątki biznesowe. Wszystkie te klasy są wspólne dla
pozostałych dwóch modułów.

\item[Moduł \texttt{unicore-beyond-back}] Reprezentuje implementację logiki biznesowej aplikacji.
Jest odpowiedzialny za warstwę utrwalania modelu danych w bazie danych PostgreSQL. Udostępnia
interfejs serwisu biznesowego po RMI. Działa jako serwlet w kontenerze serwletów (np. Apache Tomcat)
lub na serwerze aplikacji (np. JBoss).

\item[Moduł \texttt{unicore-beyond-ui}] Widoczna dla końcowego użytkownika część aplikacji.
Zawiera graficzny interfejs użytkownika (ang. GUI) napisany za pomocą GWT. Ta część aplikacji
korzysta z technik opisanych w poprzednim rozdziale. Do jej poprawnego działania musi być połączona
z instancją modułu \texttt{unicore-beyond-back} po przez RMI. Udostępniana podobnie jak moduł
opisany powyżej, jako serwlet w kontenerze serwletów lub serwerze aplikacji \footnote{Oba moduły
mogą działać na tej samej instacji kontenera serwletów lub serwera aplikacji.}.

\end{description}

Na potrzeby pisania projektu \texttt{unicore-beyond} został zaimplementowany zbiór dodatkowych bibliotek
nazwanych \texttt{stogi-java-common} \footnote{Dostępne są w pod adresem
http://code.google.com/p/stogi-java-common/ jako oprogramowanie Open Source udostępniane w ramach
Google Code.}. Zbiór ten składa się z następujących modułów:

\begin{description}

\item[Moduł \texttt{common-api}] Biblioteka udostępniająca wspólną hierarchię wyjątków biznesowych,
o które można oprzeć swoją własną hierarchię.

\item[Moduł \texttt{common-dao}] Biblioteka udostępniająca generyczne interfejsy i abstrakcyjne
implementacje warstwy utrwalania danych (ang. Data Access Object, w skrócie DAO) dla popularnej
biblioteki Hibernate.

\item[Moduł \texttt{common-gwt-dispatch}] Biblioteka dostarczająca implementację uniwersalnej
komunikacji przez mechanizm GWT RPC na zasadzie \emph{Akcji}, \emph{Wyników Akcji} i \emph{Uchwytów
Akcji}. Posiada także bardzo przydatną implementację serwletu integrującego GWT RPC z kontenerem
ziaren Spring Framework.

\item[Moduł \texttt{common-gwt-frame}] Biblioteka zawierająca szkielet aplikacji (ang. framework) do
tworzenia projektów z użyciem GWT oraz technik i wzorców opisanych w poprzednim rozdziale. Zawiera
interfejsy i abstrakcyjne implementacje \emph{Zarządców}.

\item[Moduł \texttt{common-gwt-gxt}] Biblioteka dostarczająca pomocne narzędzia do operowania na
kontrolkach biblioteki kontrolek GXT.

\item[Moduł \texttt{common-mvp}] Biblioteka zawierająca interfejsy przydatne przy stosowaniu wzorca
MVP. Przeznaczona nie tylko do aplikacji GWT. Z powodzeniem można ją wykorzystać także w aplikacjach
Swing.

\end{description}

\subsection{Model danych}

Jedną z ważniejszych prac w czasie realizacji aplikacji \texttt{unicore-beyond} było stworzenia
modelu danych, który będzie dobrze definiował graficzny interfejs użytkownika programów
udostępnianych przez system gridowy Unicore. Domyślnie model danych jest reprezentowany jako ziarna
Java (ang. JavaBean). Ułatwiło to ich utrwalenie bazie danych PostgreSQL z pomocą Hibernate.

Ogólną koncepcją przy tworzeniu modelu danych była możliwość definiowania pól dla danych wejściowych
oraz pól dla danych wyjściowych. Dodatkowo dla czytelniejszego rozmieszczenia miała istnieć
możliwość grupowania, co podczas wizualizacji modelu wiąże się z pokazywaniem ich w
formie zakładek. W tym celu powstały \emph{Definicje Wejść} i \emph{Definicje Wyjść} dla pól wejściowych i
wyjściowych, oraz \emph{Grupy Wejść} oraz \emph{Grupy Wyjść} w celu ich rozdzielenia.

\subsubsection{\emph{Definicja Zadania}}

Główną częścią modelu jest \emph{Definicja Zadania}. Posiada ona nazwę aplikacji
(\texttt{applicationName}), wersję (\texttt{applicationVersion}) praz opis
(\texttt{applicationDescription}). Zawiera referencję do \emph{Grup Wejść} (\texttt{inputGroups})
oraz \emph{Grup Wyjść} (\texttt{outputGroups}). Szkic klasy jest przedstawiony jako Kod
\ref{lst:model-task-definition}.

\begin{listing}[H]
\inputminted{java}{code/model-task-definition.java}
\caption{\emph{Definicja Zadania}, czyli klasa \texttt{TaskDefinition}}
\label{lst:model-task-definition}
\end{listing}

\subsubsection{\emph{Grupa Wejść}}

\emph{Grupa Wejść} ma zadanie porządkować \emph{Definicje Wejść}. Posiada unikalną nazwę
(\texttt{name}), uporządkowaną listę \emph{Definicji Wejść} (\texttt{inputDefinitions}), referencję
do \emph{Definicji Zadania} (\texttt{taskDefinition}), do której jest podpięta oraz kolejność
(\texttt{index}), w której jest wyświetlana użytkownikowi. Szkic klasy jest przedstawiony jako Kod
\ref{lst:model-input-group}.

\begin{listing}[H]
\inputminted{java}{code/model-input-group.java}
\caption{\emph{Grupa Wejść}, czyli klasa \texttt{InputGroup}}
\label{lst:model-input-group}
\end{listing}

\subsubsection{\emph{Definicja Wejścia}}

\emph{Definicja Wejścia} reprezentuje możliwe pola do wprowadzania danych przez użytkownika. Każdej
z definicji można zdefiniować unikalną nazwę (\texttt{name}), kolejność występowania w ramach
\emph{Grupy Wejść} (\texttt{index}), referencję do tej grupy (\texttt{inputGroup}), \emph{Typ
Wejścia} (\texttt{inputType}) oraz wartości \emph{Właściwości} (\texttt{properties}). Możliwe do
ustawienia \emph{Właściwości} określa \emph{Typ Wejścia}. Szkic klasy jest przedstawiony jako Kod
\ref{lst:model-input-definition}.

\begin{listing}[H]
\inputminted{java}{code/model-input-definition.java}
\caption{\emph{Definicja Wejścia}, czyli klasa \texttt{InputDefinition}}
\label{lst:model-input-definition}
\end{listing}

\subsubsection{\emph{Typ Wejścia}}

Zbiór \emph{Typów Wejść} definiuje programista. Widać tu przerzucenie odpowiedzialności programisty
w stosunku do jego roli w podejściach takich jak GridBean czy WebGridBean. \emph{Typ Wejścia}
posiada unikalną nazwę (\texttt{name}) oraz zbiór możliwych do konfiguracji \emph{Właściwości}
(\texttt{properties}). Szkic klasy jest przedstawiony jako Kod \ref{lst:model-input-type}.

\begin{listing}[H]
\inputminted{java}{code/model-input-type.java}
\caption{\emph{Typ Wejścia}, czyli klasa \texttt{InputType}}
\label{lst:model-input-type}
\end{listing}

\subsubsection{\emph{Grupa Wyjść}}

Model \emph{Grupy Wyjść} jest podobny do modelu \emph{Grupy Wejść}. Szkic klasy jest przedstawiony
jako Kod \ref{lst:model-output-group}.

\begin{listing}[H]
\inputminted{java}{code/model-output-group.java}
\caption{\emph{Grupa Wyjść}, czyli klasa \texttt{OutputGroup}}
\label{lst:model-output-group}
\end{listing}

\subsubsection{\emph{Definicja Wyjścia}}

Model \emph{Definicji Wyjścia} jest podobny do modelu \emph{Definicji Wejścia}. Szkic klasy jest przedstawiony
jako Kod \ref{lst:model-output-definition}.

\begin{listing}[H]
\inputminted{java}{code/model-output-definition.java}
\caption{\emph{Definicja Wyjścia}, czyli klasa \texttt{OutputDefinition}}
\label{lst:model-output-definition}
\end{listing}

\subsubsection{\emph{Typ Wyjścia}}

Model \emph{Typ Wyjścia} jest podobny do modelu \emph{Typu Wejścia}. Szkic klasy jest przedstawiony
jako Kod \ref{lst:model-output-type}.

\begin{listing}[H]
\inputminted{java}{code/model-output-type.java}
\caption{\emph{Typ Wyjścia}, czyli klasa \texttt{OutputType}}
\label{lst:model-output-type}
\end{listing}

\subsubsection{\emph{Właściwości}}

\emph{Właściwości} określają charakterystykę \emph{Typu Wejścia} lub \emph{Typu Wyjścia}. Każda z
\emph{Właściwości} może przechowywać z góry ustalony typ wartości (\texttt{valueType}). \emph{Właściwości} spełniają
znaczącą role w późniejszym wyświetlaniu i walidowaniu danych wprowadzanych przez użytkownika.
Składowe \emph{Właściwości} są przedstawione jako Kody \ref{lst:model-property-type},
\ref{lst:model-property-value} i \ref{lst:model-value-type}.

\begin{listing}[H]
\inputminted{java}{code/model-property-type.java}
\caption{\emph{Typ Właściwości}, czyli klasa \texttt{PropertyType}}
\label{lst:model-property-type}
\end{listing}

\begin{listing}[H]
\inputminted{java}{code/model-property-value.java}
\caption{\emph{Wartość Właściwości}, czyli klasa \texttt{PropertyValue}}
\label{lst:model-property-value}
\end{listing}

\begin{listing}[H]
\inputminted{java}{code/model-value-type.java}
\caption{\emph{Typ Wartości Właściwości}, czyli wyliczenie \texttt{ValueType}}
\label{lst:model-value-type}
\end{listing}

\subsubsection{Rola modelu}

Powyższy model danych poza zadaniem utrwalania graficznej reprezentacji stworzonego interfejsu
użytkownika w bazie danych, posiada także inną ważną rolę. Jest bazą do wytworzenia jego
wizualizacji w formie funkcjonalnej kontrolki GWT oraz walidatorów, które pozwolą na sprawdzanie
danych wprowadzonych przez użytkownika.

Przy okazji omawiania \emph{Typu Wejścia} zostało wspomniane przeniesienie roli programisty. Do tej pory
to właśnie programista musiał projektować cały interfejs użytkownika dla aplikacji uruchamianej na
systemie gridowym Unicore. Teraz programista będzie musiał dostarczyć instacje \emph{Typów Wejść}
oraz stowarzyszonymi z nimi kontrolkami GWT oraz walidatorami danych. Dostatecznie bogata ich liczba
powinna zaspokoić większość użytkowników, do których teraz będzie należało projektowanie interfejsów
do używanych przez nich aplikacji.

\subsection{Interfejs biznesowy}

Sercem aplikacji \texttt{unicore-beyond} jest jej część biznesowa. Jej implementacja opiera się o
trójwarstwową architekturę. Korzysta ona w pełni z funkcjonalności dostarczanych wraz ze Spring
Framework.

\subsubsection{Warstwa utrwalania danych}

Najniżej leżącą z warstw jest warstwa utrwalania danych. Zapewnia ona perzystencję do bazy danych
PostgreSQL przy użyciu narzędzia do mapowania obiektowo-relacyjnego jakim jest Hibernate.

Spring Framework dostarcza specjalne klasy pomocnicze, które pozwalają na uproszczenie pisania
obiektów dostępu do danych (ang. Data Access Objects, w skrócie DAO) dla różnych metod perzystencji.
W przypadku Hibernate jest to klasa \\
\texttt{org.springframework.orm.hibernate3.support.HibernateDaoSupport}. Opakowuje ona obiekt sesji
Hibernate, \texttt{org.hibernate.Session}, udostępniając metody typu CRUD (ang. Create Read
Update Delete), spełniające odpowiednio funkcje tworzenia, czytania, aktualizacji i usuwania encji.

Dla przyśpieszenia pisania nowych obiektów DAO oraz zachowania abstrakcji tej warstwy, względem
konkretnie wybranego sposobu perzystencji, została stworzona bazowa generyczna implementacja.

Przykład użycia pokazany został na Kodach \ref{lst:dao-interface}, \ref{lst:dao-impl},
\ref{lst:dao-example}.

\begin{listing}[H]
\inputminted{java}{code/dao-interface.java}
\caption{Generyczny interfejs DAO}
\label{lst:dao-interface}
\end{listing}

\begin{listing}[H]
\inputminted{java}{code/dao-impl.java}
\caption{Generyczna implementacja DAO}
\label{lst:dao-impl}
\end{listing}

\begin{listing}[H]
\inputminted{java}{code/dao-example.java}
\caption{Implementacja DAO dla encji \texttt{TaskDefinition}}
\label{lst:dao-example}
\end{listing}

\subsubsection{Serwis \emph{Zadania}}

Logika biznesowa aplikacji została zawarta w ramach warstwy serwisów biznesowych (ang. business
service). To tutaj dzieją się najciekawsze działania na modelu danych, które w wyniku dają pełną
funkcjonalność programu. Warstwa ta najczęściej dostaje na wejściu instancje encji i dodatkowe dane,
aby je sprawdzić (zwalidować) i przekazać do warstwy niższej, czyli DAO. Warstwa ta jest całkowicie
uzależniona od logiki biznesowej i praktycznie niemożliwe jest wyabstrachowanie jakichkolwiek
funkcjonalności. Przykład interfejsu biznesowego został zaprezentowany jako Kod
\ref{lst:service}.

\begin{listing}[H]
\inputminted{java}{code/service.java}
\caption{Interfejs serwisu \emph{Zadania}, czyli \emph{TaskService}}
\label{lst:service}
\end{listing}

\subsubsection{Walidatory \emph{Wejść}}

W ramach modelu danych, mianowicie instancji klas \emph{InputType}, został stworzony mechanizm
walidatorów, czyli prostych klas sprawdzających instację \emph{Wejścia} względem \emph{Typu
Wejścia}. Mają one za zadanie sprawdzać wprowadzone dane przez użytkownika, po stronie serwera.
Przykładowa implementacja walidatora jest pokazana jako Kod \ref{lst:validator-impl}.

%\begin{listing}[H]
%\inputminted{java}{code/validator-interface.java}
%\caption{Interfejs walidatora}
%\label{lst:validator-interface}
%\end{listing}

\begin{listing}[H]
\inputminted{java}{code/validator-impl.java}
\caption{Implementacja walidatora dla \emph{Typu Wejścia} \texttt{integerfield}}
\label{lst:validator-impl}
\end{listing}

\subsubsection{Eksportery RMI}

Trzecią i najwyższą warstwą interfejsu biznesowego jest warstwa eksporterów RMI. Udostępniają one
metody biznesowe wcześniej opisanej warstwy. Wykorzystany jest tutaj mechanizm Spring Framework,
który w prosty sposób dostarcza odpowiednią funkcjonalność. Wystarczy odpowiednio skonfigurować
odpowiednie ziarna (ang. beans). Sposób konfiguracji jest pokazany jako Kod
\ref{lst:rmi-exporter}.

\begin{listing}[H]
\inputminted{xml}{code/rmi-exporter.xml}
\caption{Konfiguracja XML ziaren eksporterów RMI}
\label{lst:rmi-exporter}
\end{listing}

\subsection{Interfejs użytkownika}

Praktyczną częścią aplikacji \texttt{unicore-beyond}, z którą ma do czynienia użytkownik jest
interfejs użytkownika. Moduł ten został napisany zgodnie ze sztuką opisaną w poprzednim rozdziale,
dlatego jego opis zostanie ograniczony.

\subsubsection{Pośrednicy RMI}

Aby móc wykorzystać funkcjonalność kodu napisanego po stronie interfejsu biznesowego, należy pobrać obiekty
udostępnione przez niego po przez mechanizm RMI. Podobnie jak wcześniej dostajemy gotowe narzędzia
dostarczane przez Spring Framework, aby osiągnąć ten cel. Musimy tylko odpowiednio skonfigurować
odpowiednie ziarna, zwane pośrednikami RMI (ang. RMI proxy). Konfiguracja ta została przedstawiona
jako Kod \ref{lst:rmi-proxy}.

\begin{listing}[H]
\inputminted{xml}{code/rmi-proxy.xml}
\caption{Konfiguracja XML ziaren pośredników RMI}
\label{lst:rmi-proxy}
\end{listing}

\subsubsection{Uchwyty Akcji}

Część \emph{Serwera} interfejsu użytkownika jest odpowiedzialna za odbieranie żądań od części
\emph{Klienta}. Funkcjonalność ta jest implementowana po przez pisanie \emph{Uchwytów Akcji}.
Korzystają one z obiektów pośredników RMI opisanych wcześniej. Przykład takiego \emph{Uchwytu akcji}
został zaprezentowany jako Kod \ref{lst:dispatch-handler}

\begin{listing}[H]
\inputminted{java}{code/dispatch-handler.java}
\caption{Implementacja \emph{Uchwytu Akcji} odpowiedzialnego za zapis \emph{Definicji Zadania}}
\label{lst:dispatch-handler}
\end{listing}

\subsubsection{Komponenty GUI}

W związku z użyciem technik projektowania aplikacji internetowych typu RIA część \emph{Klienta}
modułu \texttt{unicore-beyond-ui} została podzielona na niezależne, współpracujące ze sobą
komponenty. Podział ten został poniżej krótko opisany:

\begin{description}

\item[Edytor \emph{Zadania}] Komponent edytora modelu \emph{Definicji Zadania}. Złożony jest z kilku
mniejszych komponentów:
	
	\begin{description}

	\item[Menu edytora] Komponent menu edytora. Implementacja zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskeditor.editormenu}.

	\item[Wizualizacja \emph{Zadania}] Komponent wizualizacji tworzonej \emph{Definicji Zadania}. Implementacja
	zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskeditor.taskpreview}.
	
	\item[Narzędzia We/Wy] Komponent dostępnych do użycia \emph{Typów Wejść} i \emph{Typów Wyjściowych}.
	Implementacja zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskeditor.iotoolbox}.

	\item[Drzewo \emph{Zadania}] Komponent do operowania \emph{Definicją Zadania} w formie struktury drzewa.
	Implementacja zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskeditor.taskoutline}.

	\item[Edytor \emph{Właściwości}] Komponent do operowania \emph{Właściwościami} zdefiniowanymi dla \emph{Typów
	Wejść} i \emph{Typów Wyjść}, w zaznaczonej \emph{Definicji Wejścia} lub \emph{Definicji Wyjścia} z
	komponentu \texttt{taskoutline}. Implementacja zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskeditor.propertyeditor}.

	\end{description}

\item[Uruchamiacz \emph{Zadania}] Komponent do uruchamiania instancji \emph{Definicji Zadania}. Złożony
jest dwóch mniejszych komponentów:

	\begin{description}

	\item[Menu uruchamiacza] Komponent menu uruchamiacza. Implementacja zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskrunner.runnermenu}.

	\item[Instancja \emph{Zadania}] Komponent tworzenia instacji wybranej \emph{Definicji Zadania}. Pozwala na
	wprowadzenie danych użytkownikowi oraz ich walidację. Implementacja zawarta w pakiecie \\
	\texttt{net.stogi.unicore.beyond.ui.taskrunner.taskinstance}.

	\end{description}

\end{description}

\section{Rozszerzenia}

Jak zostało podkreślone na początku, aplikacja \texttt{unicore-beyond} jest tylko prototypem. Aby
była w pełni funkcjonalna należy włożyć w nią jeszcze trochę ciężkiej pracy. Oto propozycje, które
mogą być kolejnymi etapami jej rozwoju.

\subsection{Upiększenie kontrolek poszczególnych komponentów}

Można zastanowić się nad dodaniem większego uroku interfejsowi użytkownika, który w tej chwili, mimo
wszystko, wygląda dość spartańsko. Możnaby osiągnąć ten cel w dwojaki sposób. Dopracować obecnie
zaimplementowane kontrolki GXT albo spróbować zaimplementować własne, z użyciem
podstawowego ich zestawu dostarczanego z samym GWT. Druga opcja jest oczywiście dużo bardziej
pracochłonna, jednak efekt jaki można uzyskać przy odrobinie talentu graficznego, mógłby przewyższyć
to co reprezentują gotowe kontrolki GXT. Plusem tego podejścia jest też fakt, że własna
implementacja powinna nieść ze sobą mniej problemów z jej używaniem.

\subsection{Dodanie personalizacji}

Nie każdy z użytkowników chciałby, aby inni oglądali jego wyedytowane interfejsy aplikacji. W tym
celu należałoby dodać warstwę autoryzacji użytkowników, połączoną z personalizacją aplikacji. Jedną
z zalet takiego podejścia mogłoby być konfigurowanie wyglądu edytora względem preferencji
użytkownika. Najprostszym rozwiązaniem wydaję się być skorzystanie z Spring Security, który
w prosty sposób dałoby się zintegrować z istniejącą implementacją aplikacji. Autoryzacja wstępnie
mogłaby się opierać tylko o bazę danych PostgreSQL. Możnaby jednak pomyśleć o innych sposobach
autoryzacji. Spring Security dostarcza wiele różnych rozwiązań (np. CAS, LDAP) oraz pozwala na
napisanie własnej implementacji.

\subsection{Rozszerzenie modelu reprezentującego GUI aplikacji Unicore}

Model danych zaprezentowany w aplikacji może być bazą do rozszerzeń. Udostępnia w tej chwili dosyć
bogatą, ale jednocześnie minimalną funkcjonalność. Warto byłoby rozszerzyć możliwą ilość
typów dla \emph{Właściwości}. Chwilowo pola można ustawiać tylko jedno pod drugim. Być może godne
rozpatrzenia jest dodanie możliwości bardziej generycznego rozstawiania pól jako siatkę lub tabelę.

\subsection{Komunikacja z instancją systemu Unicore}

Aplikacja sama w sobie jest mało funkcjonalna, jeśli wprowadzonych do niej danych nie można przesłać
na serwer i otrzymać wyników jej działania. Należałoby w tym celu dodać generowanie odpowiedniego
dokumentu XML w dialekcie Simple Workflow lub JSDL. Dodatkowo trzeba by napisać kod komunikujący się
z serwerem: wysyłający zadanie, sprawdzający status wykonania, odbierający wyniki działania.

\subsection{Integracja z przyszłym portalem gridowym}

W trakcie realizacji jest polski projekt pod nazwą PL-Grid \footnote{Strona projektu:
http://www.plgrid.pl.}, którego jednym z celów jest udostępnienie ośrodkom badawczym portalu gridowego
opartego prawdopodobnie o oprogramowanie Liferay \footnote{Strona projektu:
http://www.liferay.com.}. Integracja miałaby polegać na implementacji sposobu wyświetlania aplikacji
GWT jako portlet portalu. Dodatkowo możnaby zintegrować się z mechanizmem autoryzacji portalu.

\subsection{Zastosowanie GWT 2.1}

W związku ze zmianami w podejściu projektowania aplikacji korzystających z GWT, które niesie wersja
2.1, warto byłoby rozważyć przepisanie modułu \\ \texttt{unicore-beyond-ui} na nową formę wzorca MVP.
Skorzystanie z doświadczenia, zaprawionego w bojach, zespołu Google Adwords może pomóc w poźniejszym
rozwoju interfejsu użytkownika.
